"""
股票消息分析智能体

基于新闻、公告和市场情绪进行股票消息面分析。
支持文本和JSON格式输出。
"""

from typing import Dict, Any, List, Optional, Union
from agents import BaseAgent, LLMConfig
from tools.stock_data_provider import stock_data_provider
from langchain_core.tools import Tool
import pandas as pd
import json
import re


class StockNewsAnalysisAgent(BaseAgent):
    """股票消息分析智能体"""

    def __init__(self, llm_config: Optional[LLMConfig] = None):
        super().__init__(
            name="StockNewsAnalysisAgent",
            description="股票消息分析智能体，基于新闻和公告进行消息面分析",
            llm_config=llm_config
        )

    def get_tools(self) -> List[Tool]:
        """获取消息分析所需的工具"""
        return [
            Tool(
                name="get_stock_news",
                description="获取股票相关实时新闻资讯和报道",
                func=self._get_stock_news
            ),
            Tool(
                name="analyze_news_sentiment",
                description="获取新闻数据并分析情感倾向（利好/利空/中性），提供情绪统计",
                func=self._analyze_news_sentiment
            ),
            Tool(
                name="get_company_announcements",
                description="获取公司最新公告和重大信息披露",
                func=self._get_company_announcements
            ),
            Tool(
                name="get_research_reports",
                description="获取券商研报、分析师评级和机构观点",
                func=self._get_research_reports
            ),
            Tool(
                name="analyze_market_heat",
                description="获取新闻、研报和成交数据并分析市场热度和关注度",
                func=self._analyze_market_heat
            ),
            Tool(
                name="analyze_market_impact",
                description="获取新闻和股价数据并分析消息对市场的影响程度",
                func=self._analyze_market_impact
            ),
            Tool(
                name="generate_news_signals",
                description="综合获取消息数据并生成投资信号和建议",
                func=self._generate_news_signals
            )
        ]

    def get_system_prompt(self) -> str:
        return """
        你是专业的股票消息分析智能体，基于新闻、公告和市场情绪进行综合分析。

        分析框架：
        1. 新闻内容解析：提取关键信息和情感倾向
        2. 公告重要性评估：区分常规公告和重大事项
        3. 市场情绪量化：基于多维度数据计算情绪指数
        4. 消息影响评估：判断对股价的潜在影响程度
        5. 信号生成：基于消息面给出投资建议

        输出结构：
        ## 📰 新闻概览
        - 近期重要新闻汇总
        - 新闻数量和频率统计

        ## 🎭 情感分析
        - 利好/利空/中性新闻比例
        - 整体情绪指数(-100到+100)

        ## 📊 市场热度
        - 新闻关注度评分
        - 研报覆盖情况
        - 成交活跃度

        ## 🎯 消息面信号
        - 主要信号识别
        - 影响程度评估
        - 投资建议

        ## ⭐ 消息面评分 (0-10)
        评分标准：
        - 10: 消息面极佳，重大利好频现，市场高度认可
        - 8-9: 消息面良好，积极信号明显
        - 6-7: 消息面平稳，无重大负面消息
        - 4-5: 消息面一般，存在一定不确定性
        - 2-3: 消息面较差，负面消息较多
        - 0-1: 消息面极差，重大利空频现

        最终评分：[X/10] - 评分理由

        分析原则：
        - 区分事实性公告和市场传闻
        - 考虑消息的时效性和影响力大小
        - 结合历史股价反应分析影响程度
        - 消息面分析需结合技术面和基本面

        请基于数据量化分析，避免过度解读。
        """

    async def _get_stock_news(self, stock_code: str, days: int = 7) -> str:
        """获取股票新闻"""
        try:
            news_list = await stock_data_provider.get_stock_news_sentiment(stock_code, days)

            if not news_list:
                return f"未找到股票{stock_code}最近{days}天的新闻"

            result = f"股票{stock_code}最近{days}天新闻汇总：\n\n"

            for i, news in enumerate(news_list[:10], 1):  # 最多显示10条
                title = news.get('标题', '无标题')
                time = news.get('发布时间', '未知时间')
                summary = news.get('摘要', '无摘要')

                result += f"{i}. {title}\n"
                result += f"   时间: {time}\n"
                result += f"   摘要: {summary[:100]}...\n\n"

            if len(news_list) > 10:
                result += f"... 还有{len(news_list) - 10}条新闻\n"

            return result

        except Exception as e:
            return f"获取新闻失败: {e}"

    async def _analyze_news_sentiment(self, stock_code: str) -> str:
        """分析新闻情感"""
        try:
            news_list = await stock_data_provider.get_stock_news_sentiment(stock_code, 30)  # 一个月的数据

            if not news_list:
                return f"无足够新闻数据进行情感分析"

            # 简单的关键词情感分析
            positive_keywords = ['利好', '上涨', '增长', '盈利', '合作', '并购', '投资', '突破', '创新', '获奖']
            negative_keywords = ['利空', '下跌', '亏损', '诉讼', '处罚', '风险', '危机', '退市', '违规', '调查']

            positive_count = 0
            negative_count = 0
            neutral_count = 0

            analyzed_news = []

            for news in news_list[:20]:  # 分析最近20条新闻
                title = news.get('标题', '')
                summary = news.get('摘要', '')

                content = (title + ' ' + summary).lower()

                pos_score = sum(1 for keyword in positive_keywords if keyword in content)
                neg_score = sum(1 for keyword in negative_keywords if keyword in content)

                if pos_score > neg_score:
                    sentiment = "利好"
                    positive_count += 1
                elif neg_score > pos_score:
                    sentiment = "利空"
                    negative_count += 1
                else:
                    sentiment = "中性"
                    neutral_count += 1

                analyzed_news.append({
                    'title': title,
                    'sentiment': sentiment,
                    'pos_score': pos_score,
                    'neg_score': neg_score
                })

            # 计算情感比例
            total = len(analyzed_news)
            if total == 0:
                return "无新闻数据"

            positive_ratio = positive_count / total
            negative_ratio = negative_count / total
            neutral_ratio = neutral_count / total

            result = f"股票{stock_code}新闻情感分析（最近20条）：\n\n"
            result += f"📊 情感分布：\n"
            result += f"  利好新闻: {positive_count}条 ({positive_ratio:.1%})\n"
            result += f"  利空新闻: {negative_count}条 ({negative_ratio:.1%})\n"
            result += f"  中性新闻: {neutral_count}条 ({neutral_ratio:.1%})\n\n"

            # 整体情绪判断
            if positive_ratio > 0.6:
                overall_sentiment = "🔥 整体乐观"
            elif negative_ratio > 0.6:
                overall_sentiment = "❄️ 整体悲观"
            elif abs(positive_ratio - negative_ratio) < 0.2:
                overall_sentiment = "⚖️ 整体平衡"
            else:
                overall_sentiment = "🤔 情绪偏向"

            result += f"🎯 整体情绪: {overall_sentiment}\n\n"

            # 显示部分分析结果
            result += "📋 部分新闻分析：\n"
            for news in analyzed_news[:5]:
                result += f"  • {news['title'][:30]}... [{news['sentiment']}]\n"

            return result

        except Exception as e:
            return f"分析新闻情感失败: {e}"

    async def _get_company_announcements(self, stock_code: str) -> str:
        """获取公司公告"""
        try:
            # 尝试从AKShare获取公告信息
            try:
                import akshare as ak
                announcements = ak.stock_news_em(symbol=stock_code)

                if not announcements.empty:
                    # 筛选公告类型（这里简化处理）
                    recent_announcements = announcements.head(10)

                    result = f"股票{stock_code}近期公告：\n\n"
                    for _, ann in recent_announcements.iterrows():
                        title = ann.get('标题', '无标题')
                        time = ann.get('发布时间', '未知时间')
                        result += f"• {title} ({time})\n"

                    return result
                else:
                    return f"未找到股票{stock_code}的公告信息"

            except Exception as e:
                return f"获取公告信息失败: {e}"

        except Exception as e:
            return f"获取公司公告失败: {e}"
    async def _get_research_reports(self, stock_code: str, days: int = 30) -> str:
        """获取券商研报"""
        try:
            import akshare as ak
            from datetime import datetime, timedelta
            
            result = f"股票{stock_code}券商研报汇总：\n\n"
            
            # 获取研报数据
            try:
                reports = ak.stock_research_report_em(symbol=stock_code)
                
                if reports.empty:
                    return f"未找到股票{stock_code}的研报数据"
                
                # 过滤最近days天的研报
                end_date = datetime.now()
                start_date = end_date - timedelta(days=days)
                
                if '发布时间' in reports.columns:
                    reports['发布时间'] = pd.to_datetime(reports['发布时间'])
                    recent_reports = reports[reports['发布时间'] >= start_date]
                else:
                    recent_reports = reports.head(10)  # 如果没有时间列，取最近10条
                
                if recent_reports.empty:
                    return f"最近{days}天内没有新的研报"
                
                # 统计研报评级
                rating_counts = {}
                if '投资评级' in recent_reports.columns:
                    rating_counts = recent_reports['投资评级'].value_counts().to_dict()
                
                result += f"📊 研报统计（最近{days}天）：\n"
                result += f"  研报数量: {len(recent_reports)}篇\n"
                
                if rating_counts:
                    result += "  评级分布:\n"
                    for rating, count in rating_counts.items():
                        result += f"    {rating}: {count}篇\n"
                result += "\n"
                
                # 显示部分研报
                result += "📋 最新研报：\n"
                for i, (_, report) in enumerate(recent_reports.head(5).iterrows(), 1):
                    title = report.get('研报标题', '无标题')
                    institution = report.get('研究机构', '未知机构')
                    rating = report.get('投资评级', '未评级')
                    publish_time = report.get('发布时间', '未知时间')
                    
                    result += f"{i}. {title}\n"
                    result += f"   机构: {institution} | 评级: {rating}\n"
                    result += f"   时间: {publish_time}\n\n"
                
                # 分析研报观点倾向
                if rating_counts:
                    buy_keywords = ['买入', '增持', '推荐', '强烈推荐']
                    hold_keywords = ['中性', '持有', '观望']
                    sell_keywords = ['卖出', '减持', '回避']
                    
                    buy_count = sum(count for rating, count in rating_counts.items() 
                                   if any(keyword in str(rating) for keyword in buy_keywords))
                    hold_count = sum(count for rating, count in rating_counts.items() 
                                    if any(keyword in str(rating) for keyword in hold_keywords))
                    sell_count = sum(count for rating, count in rating_counts.items() 
                                    if any(keyword in str(rating) for keyword in sell_keywords))
                    
                    total = buy_count + hold_count + sell_count
                    if total > 0:
                        result += "🎯 机构观点倾向：\n"
                        if buy_count > 0:
                            result += f"  看多: {buy_count}篇 ({buy_count/total:.1%})\n"
                        if hold_count > 0:
                            result += f"  中性: {hold_count}篇 ({hold_count/total:.1%})\n"
                        if sell_count > 0:
                            result += f"  看空: {sell_count}篇 ({sell_count/total:.1%})\n"
                        
                        if buy_count > sell_count * 2:
                            result += "  💡 机构普遍看好\n"
                        elif sell_count > buy_count * 2:
                            result += "  💡 机构普遍看空\n"
                        else:
                            result += "  💡 机构观点分歧\n"
                
                return result
                
            except Exception as e:
                return f"获取研报失败: {e}"
            
        except Exception as e:
            return f"研报分析失败: {e}"

    async def _analyze_market_heat(self, stock_code: str) -> str:
        """分析市场热度"""
        try:
            import akshare as ak
            
            result = f"股票{stock_code}市场热度分析：\n\n"
            
            # 初始化变量
            news_count_7d = 0
            report_count = 0
            volume_ratio = 0
            
            # 1. 新闻热度分析
            try:
                news_list = await stock_data_provider.get_stock_news_sentiment(stock_code, 7)
                news_count_7d = len(news_list)
                
                news_list_30d = await stock_data_provider.get_stock_news_sentiment(stock_code, 30)
                news_count_30d = len(news_list_30d)
                
                result += "📰 新闻热度：\n"
                result += f"  7天新闻数: {news_count_7d}条\n"
                result += f"  30天新闻数: {news_count_30d}条\n"
                result += f"  日均新闻: {news_count_30d/30:.1f}条\n"
                
                if news_count_7d > 10:
                    heat_level = "🔥 热度极高"
                elif news_count_7d > 5:
                    heat_level = "📈 热度较高"
                elif news_count_7d > 2:
                    heat_level = "📊 热度一般"
                else:
                    heat_level = "❄️ 热度较低"
                
                result += f"  热度评级: {heat_level}\n\n"
            except Exception as e:
                result += f"  新闻热度: 数据获取失败\n\n"
            
            # 2. 研报关注度
            try:
                reports = ak.stock_research_report_em(symbol=stock_code)
                
                if not reports.empty and '发布时间' in reports.columns:
                    from datetime import datetime, timedelta
                    end_date = datetime.now()
                    start_date = end_date - timedelta(days=30)
                    
                    reports['发布时间'] = pd.to_datetime(reports['发布时间'])
                    recent_reports = reports[reports['发布时间'] >= start_date]
                    report_count = len(recent_reports)
                    
                    result += "📊 研报关注度：\n"
                    result += f"  30天研报数: {report_count}篇\n"
                    
                    if report_count > 10:
                        attention_level = "🔥 机构高度关注"
                    elif report_count > 5:
                        attention_level = "📈 机构较为关注"
                    elif report_count > 0:
                        attention_level = "📊 机构适度关注"
                    else:
                        attention_level = "❄️ 机构关注较少"
                    
                    result += f"  关注度: {attention_level}\n\n"
                else:
                    result += "📊 研报关注度: 数据暂缺\n\n"
            except Exception as e:
                result += "📊 研报关注度: 数据获取失败\n\n"
            
            # 3. 成交活跃度
            try:
                history_data = await stock_data_provider.get_stock_history_data(stock_code)
                
                if not history_data.empty and '成交量' in history_data.columns:
                    recent_volume = history_data['成交量'].tail(5).mean()
                    avg_volume = history_data['成交量'].mean()
                    
                    volume_ratio = recent_volume / avg_volume if avg_volume > 0 else 0
                    
                    result += "💹 成交活跃度：\n"
                    result += f"  5日均量: {recent_volume:,.0f}\n"
                    result += f"  历史均量: {avg_volume:,.0f}\n"
                    result += f"  活跃度比: {volume_ratio:.2f}倍\n"
                    
                    if volume_ratio > 1.5:
                        activity_level = "🔥 成交极度活跃"
                    elif volume_ratio > 1.2:
                        activity_level = "📈 成交较为活跃"
                    elif volume_ratio > 0.8:
                        activity_level = "📊 成交正常"
                    else:
                        activity_level = "❄️ 成交清淡"
                    
                    result += f"  活跃度: {activity_level}\n\n"
                else:
                    result += "💹 成交活跃度: 数据暂缺\n\n"
            except Exception as e:
                result += "💹 成交活跃度: 数据获取失败\n\n"
            
            # 4. 综合热度评分
            result += "🎯 综合市场热度：\n"
            
            heat_score = 0
            
            # 新闻热度评分
            if news_count_7d > 5:
                heat_score += 30
            elif news_count_7d > 2:
                heat_score += 15
            
            # 研报关注度评分
            if report_count > 5:
                heat_score += 30
            elif report_count > 0:
                heat_score += 15
            
            # 成交活跃度评分
            if volume_ratio > 1.2:
                heat_score += 40
            elif volume_ratio > 0.8:
                heat_score += 20
            
            result += f"  热度得分: {heat_score}/100\n"
            
            if heat_score >= 70:
                result += "  🔥 市场高度关注，热度极高\n"
                result += "  💡 建议: 热度过高需警惕追高风险\n"
            elif heat_score >= 50:
                result += "  📈 市场较为关注，热度较高\n"
                result += "  💡 建议: 关注度适中，可适度参与\n"
            elif heat_score >= 30:
                result += "  📊 市场正常关注，热度一般\n"
                result += "  💡 建议: 关注度平稳，理性分析\n"
            else:
                result += "  ❄️ 市场关注较少，热度较低\n"
                result += "  💡 建议: 可能被市场忽视，潜在机会或风险\n"
            
            return result
            
        except Exception as e:
            return f"市场热度分析失败: {e}"


    async def _analyze_market_impact(self, stock_code: str) -> str:
        """分析消息对市场的影响"""
        try:
            # 获取新闻数据
            news_list = await stock_data_provider.get_stock_news_sentiment(stock_code, 30)

            # 获取股价数据进行相关性分析
            history_data = await stock_data_provider.get_stock_history_data(stock_code)

            if history_data.empty or not news_list:
                return "数据不足，无法分析市场影响"

            # 简单的消息-股价相关性分析
            result = f"股票{stock_code}消息面影响分析：\n\n"

            # 统计新闻数量和股价表现
            news_count = len(news_list)

            if len(history_data) >= 30:
                price_change_30d = (history_data['收盘'].iloc[-1] - history_data['收盘'].iloc[-30]) / history_data['收盘'].iloc[-30]
                volatility_30d = history_data['收盘'].pct_change().tail(30).std()

                result += f"📈 股价表现（30天）：\n"
                result += f"  涨跌幅: {price_change_30d:.2%}\n"
                result += f"  波动率: {volatility_30d:.2%}\n\n"

            result += f"📰 新闻活跃度：\n"
            result += f"  新闻数量: {news_count}条\n"
            result += f"  日均新闻: {news_count/30:.1f}条\n\n"

            # 消息密度分析
            if news_count > 10:
                news_density = "高"
                impact_desc = "消息面较为活跃，可能影响股价波动"
            elif news_count > 5:
                news_density = "中"
                impact_desc = "消息面适中，需关注重要公告"
            else:
                news_density = "低"
                impact_desc = "消息面平静，股价主要受基本面影响"

            result += f"📊 消息密度: {news_density}\n"
            result += f"💡 影响评估: {impact_desc}\n"

            return result

        except Exception as e:
            return f"分析市场影响失败: {e}"

    async def _calculate_news_score(self, sentiment_distribution: Dict[str, float],
                                  news_count_7d: int, institutional_attention: str) -> float:
        """使用大模型计算消息面评分（0-10分）"""
        try:
            # 构建消息面分析数据
            analysis_data = {
                "sentiment_distribution": sentiment_distribution,
                "news_count_7d": news_count_7d,
                "institutional_attention": institutional_attention
            }
            
            # 使用大模型进行评分
            scoring_prompt = self._get_news_scoring_prompt(analysis_data)
            llm_response = await self.llm.ainvoke(scoring_prompt)
            
            # 解析大模型响应
            scoring_result = self._parse_llm_scoring_response(llm_response)
            score = self._validate_and_clamp_score(scoring_result.get('score', 5))
            
            return score
            
        except Exception as e:
            self.logger.error(f"大模型消息面评分失败: {e}")
            # 降级到默认评分
            return 5.0

    async def _analyze_sentiment_distribution(self, stock_code: str) -> Dict[str, float]:
        """分析情感分布比例"""
        try:
            news_list = await stock_data_provider.get_stock_news_sentiment(stock_code, 30)
            
            if not news_list:
                return {"positive": 0, "neutral": 0, "negative": 0}
                
            # 情感关键词
            positive_keywords = ['利好', '上涨', '增长', '盈利', '合作', '并购', '投资', '突破', '创新', '获奖']
            negative_keywords = ['利空', '下跌', '亏损', '诉讼', '处罚', '风险', '危机', '退市', '违规', '调查']
            
            positive_count = 0
            negative_count = 0
            neutral_count = 0
            
            for news in news_list[:20]:  # 分析最近20条新闻
                title = news.get('标题', '')
                summary = news.get('摘要', '')
                content = (title + ' ' + summary).lower()
                
                pos_score = sum(1 for keyword in positive_keywords if keyword in content)
                neg_score = sum(1 for keyword in negative_keywords if keyword in content)
                
                if pos_score > neg_score:
                    positive_count += 1
                elif neg_score > pos_score:
                    negative_count += 1
                else:
                    neutral_count += 1
                    
            total = positive_count + negative_count + neutral_count
            if total == 0:
                return {"positive": 0, "neutral": 0, "negative": 0}
                
            return {
                "positive": round(positive_count / total * 100, 1),
                "neutral": round(neutral_count / total * 100, 1),
                "negative": round(negative_count / total * 100, 1)
            }
            
        except Exception as e:
            self.logger.error(f"情感分布分析失败: {e}")
            return {"positive": 0, "neutral": 0, "negative": 0}

    async def _assess_market_heat(self, stock_code: str) -> Dict[str, Any]:
        """评估市场热度"""
        try:
            # 获取7天新闻数量
            news_list_7d = await stock_data_provider.get_stock_news_sentiment(stock_code, 7)
            news_count_7d = len(news_list_7d)
            
            # 判断市场热度
            if news_count_7d > 20:
                market_heat = "极度活跃"
            elif news_count_7d > 10:
                market_heat = "较高"
            elif news_count_7d > 5:
                market_heat = "一般"
            else:
                market_heat = "较低"
                
            return {
                "market_heat": market_heat,
                "news_count_7d": news_count_7d
            }
            
        except Exception as e:
            self.logger.error(f"市场热度评估失败: {e}")
            return {"market_heat": "未知", "news_count_7d": 0}

    async def _evaluate_institutional_attention(self, stock_code: str) -> str:
        """评估机构关注度"""
        try:
            import akshare as ak
            from datetime import datetime, timedelta
            
            # 获取研报数据
            reports = ak.stock_research_report_em(symbol=stock_code)
            
            if reports.empty:
                return "一般关注"
                
            # 过滤最近30天的研报
            end_date = datetime.now()
            start_date = end_date - timedelta(days=30)
            
            if '发布时间' in reports.columns:
                reports['发布时间'] = pd.to_datetime(reports['发布时间'])
                recent_reports = reports[reports['发布时间'] >= start_date]
                report_count = len(recent_reports)
            else:
                report_count = len(reports.head(10))
                
            # 判断机构关注度
            if report_count > 10:
                return "高度关注"
            elif report_count > 5:
                return "适度关注"
            elif report_count > 0:
                return "一般关注"
            else:
                return "关注度下降"
                
        except Exception as e:
            self.logger.error(f"机构关注度评估失败: {e}")
            return "一般关注"

    def _calculate_news_confidence(self, sentiment_distribution: Dict[str, float],
                                 news_count_7d: int) -> float:
        """计算消息面分析置信度（0-1）"""
        confidence = 0.5  # 基础置信度
        
        # 基于数据质量计算置信度
        if news_count_7d > 10:
            confidence += 0.3  # 数据充足
        elif news_count_7d > 5:
            confidence += 0.2  # 数据适中
        elif news_count_7d > 0:
            confidence += 0.1  # 数据较少
            
        # 情感分布稳定性
        positive_ratio = sentiment_distribution.get('positive', 0)
        negative_ratio = sentiment_distribution.get('negative', 0)
        
        if positive_ratio > 60 or negative_ratio > 60:
            confidence += 0.2  # 情感倾向明显
        elif abs(positive_ratio - negative_ratio) > 30:
            confidence += 0.1  # 情感有偏向
            
        return round(min(confidence, 1.0), 2)

    def _generate_news_summary(self, score: float, sentiment_distribution: Dict[str, float],
                             market_heat: str, institutional_attention: str) -> str:
        """生成消息面摘要"""
        # 基于评分和数据分析生成摘要
        positive_ratio = sentiment_distribution.get('positive', 0)
        negative_ratio = sentiment_distribution.get('negative', 0)
        
        if score >= 8:
            return "消息面整体表现极佳，市场高度关注，积极信号明显"
        elif score >= 6:
            return "消息面整体表现良好，市场关注度较高，消息分布相对均衡"
        elif score >= 4:
            return "消息面整体表现一般，市场关注度正常，存在一定不确定性"
        elif score >= 2:
            return "消息面整体表现较弱，负面消息较多，市场关注度下降"
        else:
            return "消息面整体表现极差，负面消息主导，市场极度悲观"

    def _get_news_scoring_prompt(self, analysis_data: Dict[str, Any]) -> str:
        """生成消息面评分prompt"""
        sentiment_distribution = analysis_data.get("sentiment_distribution", {})
        news_count_7d = analysis_data.get("news_count_7d", 0)
        institutional_attention = analysis_data.get("institutional_attention", "未知")
        
        prompt = f"""
        你是一个专业的股票消息面分析师。请基于以下消息面数据，给出0-10分的整数评分：

        消息面分析数据：
        - 情感分布：正面 {sentiment_distribution.get('positive', 0)}%，中性 {sentiment_distribution.get('neutral', 0)}%，负面 {sentiment_distribution.get('negative', 0)}%
        - 7天新闻数量：{news_count_7d}条
        - 机构关注度：{institutional_attention}

        评分标准（严格使用0-10分制，不是百分制）：
        - 10分：消息面极佳，重大利好频现，市场高度认可，机构极度关注
        - 8-9分：消息面良好，积极信号明显，市场关注度高
        - 6-7分：消息面平稳，无重大负面消息，市场关注度正常
        - 4-5分：消息面一般，存在一定不确定性，市场关注度一般
        - 2-3分：消息面较差，负面消息较多，市场关注度下降
        - 0-1分：消息面极差，重大利空频现，市场极度悲观

        **重要提示：请严格返回0-10之间的评分，不要使用百分制（0-100）！**

        请严格按照以下JSON格式输出：
        {{
            "score": 0-10之间的整数或小数评分（例如：7、8.5等，不是70或85）,
            "reasoning": "详细的评分理由",
            "key_factors": ["关键因素1", "关键因素2", ...]
        }}

        注意：score字段必须是0-10范围内的数值，不是百分制！
        """
        
        return prompt

    def _parse_llm_scoring_response(self, llm_response: Any) -> Dict[str, Any]:
        """解析大模型评分响应"""
        try:
            # 尝试直接解析JSON
            if hasattr(llm_response, 'content'):
                content = llm_response.content
            else:
                content = str(llm_response)
            
            # 提取JSON部分
            json_match = re.search(r'\{.*\}', content, re.DOTALL)
            if json_match:
                json_str = json_match.group()
                result = json.loads(json_str)
                
                # 验证必需字段
                if 'score' in result:
                    return result
            
            # 如果JSON解析失败，尝试从文本中提取评分
            score_match = re.search(r'"score":\s*(\d+)', content)
            if score_match:
                score = int(score_match.group(1))
                return {
                    "score": score,
                    "reasoning": "从文本中提取的评分",
                    "key_factors": ["文本解析"]
                }
            
            # 如果都失败，返回默认值
            return {"score": 5, "reasoning": "解析失败，使用默认评分", "key_factors": ["解析失败"]}
            
        except Exception as e:
            self.logger.error(f"解析大模型响应失败: {e}")
            return {"score": 5, "reasoning": f"解析失败: {e}", "key_factors": ["解析错误"]}

    def _validate_and_clamp_score(self, score: Union[int, float]) -> int:
        """
        验证并限制评分在0-10范围内
        
        智能处理：
        - 自动检测百分制（0-100）并转换为十分制（0-10）
        - 对超出范围的评分进行合理限制
        - 提供详细的日志信息
        
        Args:
            score: 评分值（可能是整数、浮点数）
            
        Returns:
            0-10之间的整数评分
        """
        try:
            # 转换为浮点数
            score_float = float(score)
            
            # 智能检测：如果分数>10，可能是百分制，自动转换为十分制
            if score_float > 10:
                self.logger.warning(f"⚠️ 检测到百分制评分{score_float}，自动转换为十分制")
                score_float = score_float / 10.0
            
            # 转换为整数并限制在0-10范围内
            score_int = int(round(score_float))
            clamped_score = max(0, min(10, score_int))
            
            # 如果发生了限制，记录日志
            if score_int != clamped_score:
                self.logger.warning(f"⚠️ 评分{score_int}超出范围，已调整为{clamped_score}")
            
            return clamped_score
            
        except (ValueError, TypeError) as e:
            self.logger.warning(f"⚠️ 评分转换失败: {score}, 错误: {e}, 使用默认值5")
            return 5

    async def _generate_news_signals(self, stock_code: str, output_format: str = "text") -> Union[Dict[str, Any], str]:
        """生成消息面信号，支持文本和JSON格式输出"""
        try:
            # 获取各项分析数据
            sentiment_distribution = await self._analyze_sentiment_distribution(stock_code)
            market_heat_data = await self._assess_market_heat(stock_code)
            institutional_attention = await self._evaluate_institutional_attention(stock_code)
            
            # 计算评分和置信度
            news_score = await self._calculate_news_score(
                sentiment_distribution,
                market_heat_data.get("news_count_7d", 0),
                institutional_attention
            )
            confidence = self._calculate_news_confidence(
                sentiment_distribution,
                market_heat_data.get("news_count_7d", 0)
            )
            summary = self._generate_news_summary(
                news_score, sentiment_distribution,
                market_heat_data.get("market_heat", "未知"),
                institutional_attention
            )
            
            # 根据输出格式返回结果
            if output_format == "json":
                return {
                    "dimension": "news",
                    "score": news_score,
                    "analysis": {
                        "sentiment_distribution": sentiment_distribution,
                        "market_heat": market_heat_data.get("market_heat", "未知"),
                        "news_count_7d": market_heat_data.get("news_count_7d", 0),
                        "institutional_attention": institutional_attention,
                        "summary": summary
                    },
                    "confidence": confidence,
                    "timestamp": pd.Timestamp.now().isoformat()
                }
            else:
                # 保持向后兼容的文本输出，使用LLM评分而非硬编码计算
                sentiment_result = await self._analyze_news_sentiment(stock_code)
                impact_result = await self._analyze_market_impact(stock_code)

                # 基于分析结果生成信号（仅描述，不计算分数）
                signals = []

                # 解析情感分析结果（仅描述，不计算分数）
                if "整体乐观" in sentiment_result:
                    signals.append("✅ 消息面整体利好")
                elif "整体悲观" in sentiment_result:
                    signals.append("❌ 消息面整体利空")
                else:
                    signals.append("➡️ 消息面整体中性")

                # 解析市场影响（仅描述，不计算分数）
                if "消息面较为活跃" in impact_result:
                    signals.append("⚠️ 消息面活跃，注意风险")
                elif "消息面平静" in impact_result:
                    signals.append("🛡️ 消息面稳定，相对安全")

                # 检查是否有重大公告信号（仅描述，不计算分数）
                announcements = await self._get_company_announcements(stock_code)
                if "业绩" in announcements or "盈利" in announcements:
                    signals.append("📊 业绩相关公告，关注财务数据")
                elif "风险" in announcements or "处罚" in announcements:
                    signals.append("🚨 风险提示公告，谨慎操作")

                result = f"股票{stock_code}消息面信号：\n\n"

                for signal in signals:
                    result += f"{signal}\n"

                # 使用LLM生成的评分，而非硬编码计算
                result += f"\n📊 消息面综合评分: {news_score:.1f}/10\n"
                result += f"📈 市场热度: {market_heat_data.get('market_heat', '未知')}\n"
                result += f"🏦 机构关注: {institutional_attention}\n"
                result += f"🎯 置信度: {confidence:.1%}\n\n"
                result += f"💡 评估总结: {summary}\n"

                return result

        except Exception as e:
            error_msg = f"生成消息信号失败: {e}"
            if output_format == "json":
                return {
                    "error": error_msg,
                    "dimension": "news",
                    "score": 0.0,
                    "analysis": {
                        "sentiment_distribution": {"positive": 0, "neutral": 0, "negative": 0},
                        "market_heat": "未知",
                        "news_count_7d": 0,
                        "institutional_attention": "未知",
                        "summary": error_msg
                    },
                    "confidence": 0.0,
                    "timestamp": pd.Timestamp.now().isoformat()
                }
            else:
                return error_msg


# 全局实例
stock_news_analysis_agent = StockNewsAnalysisAgent()